package com.xsd.decorator;


/**
 * 星巴克咖啡订单项目（咖啡馆）：
 * 1) 咖啡种类/单品咖啡：Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式
 * 咖啡)、Decaf(无因咖啡)
 * 2) 调料：Milk、Soy(豆浆)、Chocolate
 * 3) 要求在扩展新的咖啡种类时，具有良好的扩展性、改动方便、维护方便
 * 4) 使用OO的来计算不同种类咖啡的费用: 客户可以点单品咖啡，也可以单品咖
 * 啡+调料组合
 *
 *
 *前面分析到方案1因为咖啡单品+调料
 * 组合会造成类的倍增，因此可以做改
 * 进，将调料内置到Drink类，这样就不
 * 会造成类数量过多。从而提高项目
 * 的维护性(如图)
 * 方案2-的问题分析
 * 1) 方案2可以控制类的数量，不至于造成很多的类
 * 2) 在增加或者删除调料种类时，代码的维护量很大
 * 3) 考虑到用户可以添加多份 调料时，可以将hasMilk 返回一个对应int
 * 4) 考虑使用 装饰者 模式
 */


/**
 * 装饰者模式定义
 * 1) 装饰者模式：动态的将新功能附加到对象上。在对象功能扩展方面，它比继承更
 * 有弹性，装饰者模式也体现了开闭原则(ocp)
 * 2) 这里提到的动态的将新功能附加到对象和ocp原则，在后面的应用实例上会以代
 * 码的形式体现，请同学们注意体会
 *
 *
 * 装饰者模式原理
 * 1) 装饰者模式就像打包一个快递  主体：比如：陶瓷、衣服 (Component) // 被装饰者
 *  包装：比如：报纸填充、塑料泡沫、纸板、木板(Decorator)
 * 2) Component
 * 主体：比如类似前面的Drink
 * 3) ConcreteComponent和Decorator
 * ConcreteComponent：具体的主体，
 * 比如前面的各个单品咖啡
 * Decorator: 装饰者，比如各调料.
 * 4) 在如图的Component与ConcreteComponent之间，如果
 * ConcreteComponent类很多,还可以设计一个缓冲层，将共有的部分提取出来，
 * 抽象层一个类
 */
public class CoffeeBar {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 装饰者模式下的订单：2份巧克力+一份牛奶的LongBlack

		// 1. 点一份 LongBlack
		Drink order = new LongBlack();
		System.out.println("费用1=" + order.cost());
		System.out.println("描述=" + order.getDes());

		// 2. order 加入一份牛奶
		order = new Milk(order);

		System.out.println("order 加入一份牛奶 费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 描述 = " + order.getDes());

		// 3. order 加入一份巧克力

		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入一份巧克力  费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入一份巧克力 描述 = " + order.getDes());

		// 3. order 加入一份巧克力

		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入2份巧克力   费用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入2份巧克力 描述 = " + order.getDes());

		System.out.println("===========================");

		Drink order2 = new DeCaf();

		System.out.println("order2 无因咖啡  费用 =" + order2.cost());
		System.out.println("order2 无因咖啡 描述 = " + order2.getDes());

		order2 = new Milk(order2);

		System.out.println("order2 无因咖啡 加入一份牛奶  费用 =" + order2.cost());
		System.out.println("order2 无因咖啡 加入一份牛奶 描述 = " + order2.getDes());


	}

}
